package com.itsu.app.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.itsu.app.exception.MyException;
import com.itsu.app.interceptor.UserThreadLocal;
import com.itsu.commons.utils.VoUtil;
import com.itsu.interfaces.entity.Album;
import com.itsu.interfaces.entity.Comment;
import com.itsu.interfaces.entity.Publish;
import com.itsu.interfaces.entity.UserInfoEntity;
import com.itsu.interfaces.service.PublishService;
import com.itsu.pojo.constants.Constants;
import com.itsu.pojo.enums.CommentType;
import com.itsu.pojo.enums.ResultCode;
import com.itsu.pojo.results.ErrorResult;
import com.itsu.pojo.vo.PageResult;
import com.itsu.pojo.vo.QuanZiVo;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

@Service
public class AppPublishService {

    @Reference
    PublishService publishService;

    @Autowired
    IdService idService;

    @Autowired
    AppAlbumService appAlbumService;

    @Autowired
    AppTimeLineService appTimeLineService;

    @Autowired
    AppUserInfoService appUserInfoService;

    @Autowired
    AppCommentService appCommentService;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    public void publish(String textContent, String location, String latitude, String longitude, MultipartFile[] multipartFile) throws IOException {

        if (StrUtil.isBlank(textContent)) {
            throw new MyException(new ErrorResult(ResultCode.PUBLISH_CONTEXT_NULL));
        }

        Long uid = UserThreadLocal.getUid();

        List<String> medias = new ArrayList<>();
//        for (MultipartFile file : multipartFile) {
//            String pictureUrl = OssUtil.saveImage(file.getBytes(),
//                   StrUtil.subAfter(file.getOriginalFilename(), ".", true));
//        }
        medias.add("https://xaingmall.oss-cn-hangzhou.aliyuncs.com/images/2021/11/8/fb2f4aa1b523429a9002fd2fbcd9bad2.webp");

        Publish publish = new Publish();
        publish.setId(new ObjectId());
        publish.setPid(idService.createId("PUBLISH"));
        publish.setUserId(uid);
        publish.setText(textContent);
        publish.setMedias(medias);
        publish.setSeeType(1);
        publish.setSeeList(new ArrayList<>());
        publish.setNotSeeList(new ArrayList<>());
        publish.setLocationName(location);
        publish.setLatitude(latitude);
        publish.setLongitude(longitude);
        publish.setCreated(System.currentTimeMillis());

        ObjectId publishId = publishService.savePublish(publish);

        appAlbumService.saveAlbum(publishId, uid);

        appTimeLineService.saveFriendsTimeLine(publishId, uid);
    }

    public PageResult friendsQunzi(Integer page, Integer pagesize) {
        //todo 对于page、pagesize的校验
        List<Publish> publishList = publishService.findFriendsQunzi(page, pagesize, UserThreadLocal.getUid());
        if (CollUtil.isEmpty(publishList)) {
            return new PageResult();
        }

        Long count = publishService.countOfFriendQunzi(UserThreadLocal.getUid());

        List<Long> userIds = CollUtil.getFieldValues(publishList, "userId", Long.class);

        Map<Long, UserInfoEntity> map = new HashMap<>();
        for (Long userId : userIds) {
            map.put(userId, appUserInfoService.findUserByUid(userId));
        }

        List<QuanZiVo> ziVoList = new ArrayList<>();
        for (Publish publish : publishList) {
            ObjectId publishId = publish.getId();
            Long userId = publish.getUserId();
            Long likedCount = appCommentService.queryLikedCount(publishId);
            Long commentCount = appCommentService.queryCommentCount(publishId);
            Long lovedCount = appCommentService.queryLovedCount(publishId);
            Long hasLiked = appCommentService.queryCommentStatus(publishId, userId, CommentType.LIKED.getValue());
            Long hasLoved = appCommentService.queryCommentStatus(publishId, userId, CommentType.LOVED.getValue());
            QuanZiVo quanzi = VoUtil.Quanzi(map.get(userId), publish);
            quanzi.setLikeCount(Convert.toInt(likedCount, 0));
            quanzi.setCommentCount(Convert.toInt(commentCount, 0));
            quanzi.setLoveCount(Convert.toInt(lovedCount, 0));
            quanzi.setHasLiked(Convert.toInt(hasLiked));
            quanzi.setHasLoved(Convert.toInt(hasLoved));
            ziVoList.add(quanzi);
        }

        return new PageResult(page, pagesize, count, ziVoList);
    }

    public PageResult recommendFriendQunzi(Integer page, Integer pagesize) {
        //todo 对于page、pagesize的校验
        String pids = redisTemplate.opsForValue().get(Constants.QUANZI_PUBLISH_RECOMMEND + UserThreadLocal.getUid());
        List<Publish> publishList = Collections.emptyList();
        if (StrUtil.isBlank(pids)) {
            publishList =  publishService.randomMovements(pagesize);
        } else {
            Integer startIndex = (page - 1) * pagesize;
            Integer endIndex = NumberUtil.min(page * pagesize, pids.length());

            List<String> pisList = CollUtil.sub(StrUtil.split(pids, ","), startIndex, endIndex);
            publishList = publishService.findMovementsByPids(pisList);
        }

        Long count = publishService.countOfPublish();

        List<Long> userIds = CollUtil.getFieldValues(publishList, "userId", Long.class);

        Map<Long, UserInfoEntity> map = new HashMap<>();
        for (Long userId : userIds) {
            map.put(userId, appUserInfoService.findUserByUid(userId));
        }

        List<QuanZiVo> ziVoList = new ArrayList<>();
        for (Publish publish : publishList) {
            ObjectId publishId = publish.getId();
            Long userId = publish.getUserId();
            Long likedCount = appCommentService.queryLikedCount(publishId);
            Long commentCount = appCommentService.queryCommentCount(publishId);
            Long lovedCount = appCommentService.queryLovedCount(publishId);
            Long hasLiked = appCommentService.queryCommentStatus(publishId, userId, CommentType.LIKED.getValue());
            Long hasLoved = appCommentService.queryCommentStatus(publishId, userId, CommentType.LOVED.getValue());
            QuanZiVo quanzi = VoUtil.Quanzi(map.get(userId), publish);
            quanzi.setLikeCount(Convert.toInt(likedCount, 0));
            quanzi.setCommentCount(Convert.toInt(commentCount, 0));
            quanzi.setLoveCount(Convert.toInt(lovedCount, 0));
            quanzi.setHasLiked(Convert.toInt(hasLiked));
            quanzi.setHasLoved(Convert.toInt(hasLoved));
            ziVoList.add(quanzi);
        }

        return new PageResult(page, pagesize, count, ziVoList);
    }

    public PageResult mySelfFriendQunzi(Integer page, Integer pageSize, Long userId) {
        List<Album> albumsList = appAlbumService.findAlbums(userId);
        List<Album> albums = CollUtil.sub(albumsList, (page - 1) * pageSize,
                NumberUtil.min(page * pageSize, albumsList.size()));

        UserInfoEntity userInfo = appUserInfoService.findUserByUid(userId);

        List<ObjectId> publishIdList = CollUtil.getFieldValues(albums, "publishId", ObjectId.class);

        List<QuanZiVo> ziVoList = new ArrayList<>();
        for (ObjectId objectId : publishIdList) {
            Publish publish = publishService.findOneById(objectId);
            Long likedCount = appCommentService.queryLikedCount(objectId);
            Long commentCount = appCommentService.queryCommentCount(objectId);
            Long lovedCount = appCommentService.queryLovedCount(objectId);
            Long hasLiked = appCommentService.queryCommentStatus(objectId, userId, CommentType.LIKED.getValue());
            Long hasLoved = appCommentService.queryCommentStatus(objectId, userId, CommentType.LOVED.getValue());
            QuanZiVo quanzi = VoUtil.Quanzi(userInfo, publish);
            quanzi.setLikeCount(Convert.toInt(likedCount, 0));
            quanzi.setCommentCount(Convert.toInt(commentCount, 0));
            quanzi.setLoveCount(Convert.toInt(lovedCount, 0));
            quanzi.setHasLiked(Convert.toInt(hasLiked));
            quanzi.setHasLoved(Convert.toInt(hasLoved));
            ziVoList.add(quanzi);
        }

        return new PageResult(page, pageSize, Convert.toLong(albumsList.size()), ziVoList);
    }

    public Long loveMovements(String publishId) {
        Publish publisher = publishService.findOneById(new ObjectId(publishId));
        Comment comment = Comment.builder()
                .publishId(new ObjectId(publishId))
                .userId(UserThreadLocal.getUid())
                .publishUserId(publisher.getUserId())
                .commentType(CommentType.LOVED.getValue())
                .content(null)
                .isParent(false)
                .parentId(null)
                .created(System.currentTimeMillis())
                .build();
         return appCommentService.loveComment(comment);
    }

    public Long unLoveMovements(String publishId) {
        Publish publisher = publishService.findOneById(new ObjectId(publishId));
        Comment comment = Comment.builder()
                .publishId(new ObjectId(publishId))
                .userId(UserThreadLocal.getUid())
                .publishUserId(publisher.getUserId())
                .commentType(CommentType.LOVED.getValue())
                .content(null)
                .isParent(false)
                .parentId(null)
                .created(System.currentTimeMillis())
                .build();
        return appCommentService.unLoveComment(comment);
    }

    public Long likeMovements(String publishId) {
        Publish publisher = publishService.findOneById(new ObjectId(publishId));
        Comment comment = Comment.builder()
                .publishId(new ObjectId(publishId))
                .userId(UserThreadLocal.getUid())
                .publishUserId(publisher.getUserId())
                .commentType(CommentType.LIKED.getValue())
                .content(null)
                .isParent(false)
                .parentId(null)
                .created(System.currentTimeMillis())
                .build();
        return appCommentService.likeComment(comment);
    }


    public Long dislikeMovements(String publishId) {
        Publish publisher = publishService.findOneById(new ObjectId(publishId));
        Comment comment = Comment.builder()
                .publishId(new ObjectId(publishId))
                .userId(UserThreadLocal.getUid())
                .publishUserId(publisher.getUserId())
                .commentType(CommentType.LIKED.getValue())
                .content(null)
                .isParent(false)
                .parentId(null)
                .created(System.currentTimeMillis())
                .build();
        return appCommentService.dislikeComment(comment);
    }

    public Publish findOnePublish(String publishId) {
        Publish publisher = publishService.findOneById(new ObjectId(publishId));
        return publisher;
    }

    public QuanZiVo findOneMovement(ObjectId publishId) {
        Publish publish = publishService.findOneById(publishId);
        UserInfoEntity userByUid = appUserInfoService.findUserByUid(publish.getUserId());
        Long likedCount = appCommentService.queryLikedCount(publishId);
        Long commentCount = appCommentService.queryCommentCount(publishId);
        Long lovedCount = appCommentService.queryLovedCount(publishId);
        Long hasLiked = appCommentService.queryCommentStatus(publishId, publish.getUserId(), CommentType.LIKED.getValue());
        Long hasLoved = appCommentService.queryCommentStatus(publishId, publish.getUserId(), CommentType.LOVED.getValue());
        QuanZiVo quanzi = VoUtil.Quanzi(userByUid, publish);
        quanzi.setLikeCount(Convert.toInt(likedCount, 0));
        quanzi.setCommentCount(Convert.toInt(commentCount, 0));
        quanzi.setLoveCount(Convert.toInt(lovedCount, 0));
        quanzi.setHasLiked(Convert.toInt(hasLiked));
        quanzi.setHasLoved(Convert.toInt(hasLoved));
        return quanzi;
    }
}
